package Java8新日期时间API;

import org.junit.Test;

import java.beans.Transient;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.Temporal;
import java.time.temporal.TemporalAdjuster;
import java.time.temporal.TemporalAdjusters;
import java.util.Set;

/*
    Instant: 瞬时实例
    LocalDate: 本地日期,不包含具体时间,例如: 2014-01-14 可以用来记录生日、纪念日、加盟日等
    LocalTime: 本地时间,不包含日期
    LocalDateTime: 组合了日期和时间,但不包含时差和时区信息
    ZonedDateTime: 最完整的日期时间,包含时区和相对UTC或格林威治的时差
*/
public class DateTest05 {

    //获取当前的日期(只有日期,不包含时间)
    @Test
    public void test1() {
        LocalDate today = LocalDate.now();
        System.out.println(today);

        int year = today.getYear();
        int monthValue = today.getMonthValue();
        int day = today.getDayOfMonth();
        System.out.printf("Year: %d Month: %d day: %d t %n", year, monthValue, day);
    }

    // LocalDate.of() 创建任意日期
    @Test
    public void test2() {
        LocalDate date = LocalDate.of(2021, 10, 26);
        System.out.println(date);
    }

    // 判断两个日期是否相等
    @Test
    public void test3() {
        // 如果比较的日期是字符型的,需要先解析成日期对象再作判断
        LocalDate today = LocalDate.now();
        LocalDate yesterday = LocalDate.of(2021, 10, 25);
        System.out.println(today.equals(yesterday));
    }

    //检查类似生日、纪念日、法定假日(国庆以及春节),或者每个月固定时间发送邮件给客户,这些周期性事件
    @Test
    public void test4() {
//        LocalDate today = LocalDate.now();
        LocalDate today = LocalDate.of(2021, 3, 20);
        LocalDate dateOfBirth = LocalDate.of(1996, 3, 20);

        // MonthDay 类,这个类组合了月份和日,去掉了年,所以可以用它判断每年都会发生事件,类似的还有 YearMonth 类
        MonthDay birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth());
        MonthDay currentMonthDay = MonthDay.from(today);

        if (currentMonthDay.equals(birthday)) {
            System.out.println("生日快乐");
        } else {
            System.out.println("生日还没到");
        }
    }

    //获取当前时间(只有时间没有日期)
    @Test
    public void test5() {
        LocalTime now = LocalTime.now();
        System.out.println(now);
    }

    //在现有的时间上增加小时
    @Test
    public void test6() {
        //返回一个全新的 LocalTime 实例,由于其不可变性,所以返回后一定要用变量赋值
        LocalTime now = LocalTime.now();
        //增加 2 小时
        LocalTime localTime = now.plusHours(2);
        System.out.println(localTime);
    }

    //计算一个星期之后的日期
    @Test
    public void test7() {
        // ChronoUnit类声明了时间单位,可以用同样的方法增加1个月、1年、1小时、1分钟甚至一个世纪,由于 LocalDate 也是不变类型,返回后一定要用变量赋值
        LocalDate today = LocalDate.now();
        LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
        System.out.println(today);
        System.out.println(nextWeek);
    }

    //计算一年前或一年后的日期
    @Test
    public void test8() {
        LocalDate today = LocalDate.now();
        LocalDate previousYear = today.minus(1, ChronoUnit.YEARS);
        System.out.println(previousYear);

        LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
        System.out.println(nextYear);
    }

    // Clock 时钟类
    @Test
    public void test9() {
        // Java 8增加了一个 Clock 时钟类用于获取当时的时间戳或当前时区下的日期时间信息,以前用到 System.currentTimeInMillis()和 TimeZone.getDefault() 的地方都可用 Clock 替换
        //根据系统时间返回当前时间并设置为 UTC
        Clock clock = Clock.systemUTC();
        System.out.println(clock);

        //根据系统时钟区域返回时间
        Clock defaultClock = Clock.systemDefaultZone();
        System.out.println(defaultClock);
    }

    //判断日期是早于还是晚于另一个日期
    @Test
    public void test10() {
        // LocalDate 类有两类方法 isBefore() 和 isAfter() 用于比较日期,调用 isBefore() 方法时,如果给定日期小于当前日期则返回 true
        LocalDate today = LocalDate.now();
        LocalDate tomorrow = LocalDate.of(2021, 10, 25);

        System.out.println(tomorrow.isAfter(today));

        //减去一天
        LocalDate yesterday = today.minus(1, ChronoUnit.DAYS);
        System.out.println(yesterday.isBefore(today));
    }

    //处理时区
    @Test
    public void test11() {
        // Java 8 不仅分离了日期和时间,也把时区分离出来了,现在有一系列单独的类如 ZoneId 来处理特定时区,ZoneDateTime 类来表示某时区下的时间
        //设置时区
        ZoneId america = ZoneId.of("America/New_York");
        LocalDateTime localDateAndTime = LocalDateTime.now();
        ZonedDateTime dateAndTimeInNewYork = ZonedDateTime.of(localDateAndTime, america);
        System.out.println("现在的日期和时间在特定的时区: " + dateAndTimeInNewYork);
    }

    //固定日期
    @Test
    public void test12() {
        //与 MonthDay 检查重复事件的例子相似, YearMonth 是另一个组合类,用于表示信用卡到期日、FD到期日、期货期权到期日等,还可以用这个类得到当月共有多少天, YearMonth 实例的 lengthOfMonth() 方法可以返回当月的天数,在判断 2 月有 28 天还是 29 天时非常有用
        YearMonth currentYearMonth = YearMonth.now();
        System.out.println(currentYearMonth);
        System.out.println(currentYearMonth.lengthOfMonth());

        YearMonth creditCardExpiry = YearMonth.of(2028, Month.FEBRUARY);
        System.out.println(creditCardExpiry);
    }

    //检查闰年
    @Test
    public void test13(){
        LocalDate today = LocalDate.now();
        System.out.println(today.isLeapYear());
    }

    //计算两个日期之间的天数和月数
    @Test
    public void test14(){
        //计算两个日期之间的天数、周数或月数,在Java 8中可以用java.time.Period类来做计算
        LocalDate today = LocalDate.now();
        LocalDate last = LocalDate.of(2021, 5, 26);

        Period period = Period.between(last, today);
        System.out.println(period.getMonths());
        System.out.println(period.getDays());
    }

    //包含时差信息的日期和时间
    @Test
    public void test15(){
        //ZoneOffset类用来表示时区,举例来说印度与GMT或UTC标准时区相差+05:30,可以通过 ZoneOffset.of() 静态方法来获取对应的时区。一旦得到了时差就可以通过传入 LocalDateTime 和 ZoneOffset 来创建一个 OffSetDateTime 对象
        LocalDateTime datetime = LocalDateTime.of(2018, Month.FEBRUARY, 14, 19, 30);
        ZoneOffset offset = ZoneOffset.of("+05:30");
        OffsetDateTime date = OffsetDateTime.of(datetime, offset);
        System.out.println("Date and Time with timezone offset in Java : " + date);
    }

    //获取当前的时间戳
    @Test
    public void test16(){
        Instant timestamp = Instant.now();
        System.out.println(timestamp);
    }

    //使用预定义的格式化工具去解析或格式化日期
    @Test
    public void test17(){
        String dayAfterTomorrow = "20211026";
        LocalDate formatted = LocalDate.parse(dayAfterTomorrow, DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(formatted);
    }

}
